Portfolio
A diversified portfolio is made through proportionate allocation of the budget in each of the shortlists.
def portfolio(shortlist):
shortlist["units"] = ((shortlist["score"] * 1000000) / (shortlist["score"].sum() * shortlist["Current Price"])).round().astype(int)
shortlist["spent"] = shortlist["units"] * shortlist["Current Price"]
shortlist["appreciation"] = shortlist["spent"] * (100 + shortlist["growth"]) / 100
shortlist = shortlist[shortlist["units"] != 0]
shortlist = shortlist[["join_key", "Current Price", "t_2_price", "score", "cumulative", "units", "spent", "appreciation"]]
return shortlist
portfolios = []
for i in range(1, 5):
shortlist = pd.read_csv(f"shortlists/shortlist{i}.csv")
portfolios.append(portfolio(shortlist))
The units to be bought of each stock is computed as the fraction of the total score as a fraction of the budget (1,000,000 in this case) divided by the current price. It is rounded off to the nearest integer.
The amount spent in buying the stock is then calculated as the number of units bought multiplied by the current price, which may be different from the fraction of the total budget computed earlier since the units have been rounded off.
The appreciation in price is computed using the estimated growth percentage over the amount spent.
But the final shortlisting hyperparameters can be optimized to give maximum growth.
def objective(trial):
df = pd.read_csv("stocks/prediction.csv")
w1 = trial.suggest_float("w1", 0.01, 5)
w2 = trial.suggest_float("w2", 0.01, 5)
min_score = trial.suggest_float("min_score", 0, 20)
size = trial.suggest_int("size", 5, 20)
df["cumulative"] = df["score"] + w1 * (df["MACD"] - df["MACD Signal"]) + w2 * (df["Graham"] - df["Current Price"])
shortlist = df[df["score"] > min_score].sort_values(by="cumulative", ascending=False).iloc[:size, :]
shortlist = portfolio(shortlist)
return (shortlist.appreciation.sum() - shortlist.spent.sum()) * 100 / shortlist.spent.sum()
study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=1000)
study.best_trial
# 'w1': 0.47680498253512527, 'w2': 0.012711169376892626, 'min_score': 19.137374775059655, 'size': 6
The total returns of each portfolio is estimated as:
growth = {f"portfolio_{i + 1}": (portfolios[i].appreciation.sum() - portfolios[i].spent.sum()) * 100 / portfolios[i].spent.sum() for i in range(len(portfolios))}
growth
# {'portfolio_1': 33.29093704652035,
# 'portfolio_2': 17.759494837375748,
# 'portfolio_3': 10.375173428855186,
# 'portfolio_4': 33.30796555169246}
Thus, the final portfolio has an expected return of 33.3%.